package listen

import (
	"bytes"
	"fmt"
	"net"

	library ".."
	dispatcher "../dispatcher"
	"../log"
)

// Log 全局日志
var Log = log.GetLog("library")

// Addr 链接地址
type Addr struct {
	Network   string   // 链接类型
	TCPClose  bool     // TCP关闭
	TCPListen net.Conn // TcpConn类
	// UDP
	UDPConn *net.UDPConn // UDPConn类
	UDPAddr *net.UDPAddr // UDPAddr类
	// 参数数据
	Data *bytes.Buffer // 得到数据
}

// Write 写数据
func (L *Addr) Write(Value []byte) {
	switch L.Network {
	case "tcp":
		L.TCPListen.Write(Value)
	case "udp":
		_, err := L.UDPConn.WriteToUDP(Value, L.UDPAddr)
		if err != nil {
			Log.ErrorS(fmt.Sprintf("UDP写数据失败: %v", err))
		}
	default:
		Log.ErrorS("写数据失败:未知协议")
	}
}

// Listen 链接类
type Listen struct {
	Buffer   library.Buffer      // 缓冲
	Dispatch dispatcher.Dispatch // 链接调度
}

// Init 初始化
func (L *Listen) Init(min int, max int, Value func(Value *Addr) int) {
	// 创建调度
	L.Buffer.Init(max)
	L.Dispatch = dispatcher.Dispatch{}
	// 调度器
	L.Dispatch.Init(min, max, true, true, func(value interface{}) int {
		if add, ok := value.(*Addr); ok {
			return Value(add)
		}
		Log.ErrorS("获取缓存失败,断言无效")
		return -1 // -1 退出链接 默认0不退出链接
	})
}

// Listen 链接
func (L *Listen) Listen(network, address string) {
	// 缓冲区
	data := make([]byte, 1024)
	// 处理链接
	switch network {
	case "tcp", "tcp4", "tcp6", "unix", "unixpacket":
		// 初始化链接
		tcp, err := net.Listen("tcp", address)
		defer tcp.Close() // 关闭
		if err != nil {
			Log.ErrorS(fmt.Sprintf("初始化链接失败: %v", err))
			return
		}
		// 调度循环
		for {
			// 等待参数
			conn, err := tcp.Accept()
			if err != nil {
				Log.ErrorS(fmt.Sprintf("接受链接失败: %v", err))
				break
			}
			// 处理链接
			go func() {
				for {
					n, err := conn.Read(data)
					// 检测关闭
					if err != nil {
						break
					}
					// 获得缓冲对象
					B, arr := L.getBuffer()
					// 设置数据
					arr.Network = "tcp"
					arr.TCPListen = conn
					// 设置得到数据
					arr.Data.Write(data[:n])
					// 返回
					lock := L.Dispatch.Get()
					lock.Set(B.Value) // 发送参数
					// 卡主线程数量 -1 退出链接
					if <-lock.Lock == -1 || arr.TCPClose {
						B.Employ = false // 释放
						break
					}
					B.Employ = false // 释放
				}
				conn.Close()
			}()

		}
	case "udp", "udp4", "udp6":
		// 初始化链接地址
		addr, err := net.ResolveUDPAddr("udp", address)
		if err != nil {
			Log.ErrorS(fmt.Sprintf("初始化链接地址失败: %v", err))
			return
		}
		udp, err := net.ListenUDP("udp", addr)
		defer udp.Close()
		if err != nil {
			Log.ErrorS(fmt.Sprintf("初始化链接失败: %v", err))
			return
		}
		// 调度循环
		for {
			n, rAddr, err := udp.ReadFromUDP(data)
			if err != nil {
				Log.ErrorS(fmt.Sprintf("接受链接失败: %v", err))
				break
			}
			// 获得缓冲对象
			B, arr := L.getBuffer()
			// 设置数据
			arr.Network = "udp"
			arr.UDPAddr = rAddr
			arr.UDPConn = udp
			// 得到数据
			arr.Data.Write(data[:n])
			// 返回
			lock := L.Dispatch.Get()
			lock.Set(B.Value)
			<-lock.Lock
			B.Employ = false // 释放缓冲
		}
	default:
		Log.ErrorS("接受链接失败链接类型错误")
	}
}

// getBuffer 得到缓冲
func (L *Listen) getBuffer() (buffer *library.BufferByte, addr *Addr) {
	// 获得缓冲
	buffer = L.Buffer.Get()
	// 初始化传递参数
	if buffer.Value == nil {
		addr = &Addr{
			Data:     bytes.NewBuffer([]byte{}), // 读
			TCPClose: false}
		buffer.Value = addr
	} else {
		if add, ok := buffer.Value.(*Addr); ok {
			addr = add
			// 初始化
			addr.TCPClose = false
			addr.TCPListen = nil
			addr.UDPAddr = nil
			addr.UDPConn = nil
			addr.Data.Reset()
		} else {
			Log.ErrorS("获取缓存失败,断言无效")
		}
	}
	return
}
